#include "AliveConsumer.h"

#define ALLOW_LOCALHOST		//for debug
#define CONN_PORT 54303
#define TTL 32

/**
 * Constructor
 */
AliveConsumer::AliveConsumer()
{	
	port = CONN_PORT;
	ttl = TTL;
}

/**
 * Deconstructor
 */
AliveConsumer::~AliveConsumer()
{
	delete sock;
}

/**
 * Override QThread::run()
 */
void AliveConsumer::run()
{
	qDebug() << "Alive Consumer thread started" << this;
	
	sock = new QUdpSocket();
	
	if(sock->bind(port, QUdpSocket::ShareAddress) == false)
	{
		qWarning() << "unable to bind alive consumer socket";
		
		//TODO: emit signal!
	}
	
	/**
	 * Set the socket as multicast
	 */
	int consumerSockDescriptor = sock->socketDescriptor();
	
	if(consumerSockDescriptor == -1)
	{
		qWarning() << "Warning: socket descriptor for alive multicast consumer failed";
		//TODO: emit signal and stop all
	}
	
	struct sockaddr_in sendAddr;
	memset(&sendAddr, 0, sizeof(sendAddr));
	sendAddr.sin_family = AF_INET;
	sendAddr.sin_addr.s_addr = inet_addr("238.38.38.38"); //Chosen Broadcast address!!
	sendAddr.sin_port = htons(port);

	struct ip_mreq mreq;
	memset(&mreq, 0, sizeof(struct ip_mreq));
	mreq.imr_multiaddr.s_addr = inet_addr("238.38.38.38"); // group addr
	mreq.imr_interface.s_addr = htons(INADDR_ANY); // use default
	
	// set the TTL
	if (setsockopt(consumerSockDescriptor, IPPROTO_IP,
			IP_MULTICAST_TTL, (const char *)&ttl, sizeof(ttl) ) < 0)
	{
		int errsv = errno;
		//TODO emit critical signal
		qWarning() << "Alive Consumer: setsocket option failed! (TTL)" << "errno:" << strerror(errsv);
				
	}
	
	//Make this a member of the Multicast Group
	if(setsockopt(consumerSockDescriptor, IPPROTO_IP, 
			IP_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq)) < 0)
	{
		int errsv = errno;
		//TODO emit critical signal
		qWarning() << "Alive Consumer: setsocket option failed! (MEMBERSHIP)" << "errno:" << strerror(errsv);

	}
	
	
	/* connect the readyRead signal */
	connect(sock, SIGNAL(readyRead()),
			this, SLOT(readMulticastDatagram()));
	
	exec();		//start the thread loop and wait until exit() is called
}

/**
 * Slot: read ALIVE datagram from multicast socket
 */
void AliveConsumer::readMulticastDatagram()
{
	while (sock->hasPendingDatagrams())
	{
		QByteArray datagram;
		datagram.resize(sock->pendingDatagramSize());
		
		QHostAddress sender;
		quint16 senderPort;
		
		sock->readDatagram(datagram.data(), datagram.size(),
		&sender, &senderPort);
		
		qDebug() << "Received ALIVE From: " + sender.toString() + ":" + QByteArray::number(senderPort);
		
		// parse the datagram if the sender != myself
#ifndef ALLOW_LOCALHOST
		if(!QNetworkInterface::allAddresses().contains(sender))
#endif
			MessageParser::getInstance()->parseString(&datagram, sender);
	}
}
